#!/usr/bin/env python
# -*- coding: utf-8 -*-
# ==================================================
# @File    : logger
# @IDE     : PyCharm
# @Author  : liuxiangui
# @Date    : 2023/12/9 11:12
# @Describe: 日志模块
# ==================================================
import logging
import traceback
import re
import sys
import os
import allure
import colorlog
from library.tools.json_driver import JsonDriver

LOG_FORMAT = r"{filename}:{lineno} {data}"
REG_FILE_INFO = r'File "(.*?)", line (\d*),'
PYTEST_KEY = r"/_pytest/"
LOG_METHOD = "allure"


def get_caller():
    custom_stacks = []
    stacks = traceback.format_stack()
    stacks.reverse()
    stacks = [[line.strip() for line in s.splitlines()] for s in stacks]
    for line in stacks:
        if len(line) == 2:
            file_info, func_info = line
        elif len(line) == 1:
            file_info = line[0]
        else:
            continue
        search_res = re.search(REG_FILE_INFO, file_info)
        if not search_res:
            continue
        file_name = search_res.group(1)
        file_line = search_res.group(2)
        if PYTEST_KEY in file_name:
            break
        custom_stacks.append([file_name, file_line, func_info])
    caller_file, lineno, func = custom_stacks[-1]
    case_file = os.path.basename(caller_file)
    return case_file, lineno, func


class Logger:
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, "instance"):
            cls.instance = super().__new__(cls)
        return cls.instance

    def __init__(self, exc_info=False):
        self.excInfo = exc_info
        self.logger = logging.getLogger(__name__)
        # self.logger.addHandler(logging.StreamHandler())
        formattter = self.log_color()
        screen_output = logging.StreamHandler()
        screen_output.setFormatter(formattter)
        self.logger.addHandler(screen_output)

    @classmethod
    def log_color(cls):
        """ 设置日志颜色 """
        log_colors_config = {
            'DEBUG': 'cyan',
            'INFO': 'green',
            'WARNING': 'yellow',
            'ERROR': 'red',
            'CRITICAL': 'red',
        }

        formatter = colorlog.ColoredFormatter(
            '%(log_color)s[%(asctime)s] [%(name)s] [%(levelname)s]: %(message)s',
            log_colors=log_colors_config
        )
        return formatter

    def info(self, msg, *args, **kwargs):
        sys.getfilesystemencoding()
        self.logger.setLevel("INFO")
        if "html" in kwargs:
            kwargs.pop("html")
        if isinstance(msg, list) or isinstance(msg, dict):
            # msg = pretty_print(msg)
            msg = JsonDriver.json_pretty_print(msg)
        data = msg
        self.logger.info(msg=data, *args, **kwargs, exc_info=self.excInfo)

    def warn(self, *args, **kwargs):
        self.logger.setLevel("WARNING")
        self.logger.warning(*args, **kwargs, exc_info=self.excInfo)

    def error(self, msg, *args, **kwargs):
        self.logger.setLevel("ERROR")
        if "html" in kwargs:
            kwargs.pop("html")
        case_file, lineno, func = get_caller()
        data = LOG_FORMAT.format(filename=case_file, lineno=lineno, func=func, data=msg)
        self.logger.error(msg=data, *args, **kwargs, exc_info=self.excInfo)

    def debug(self, *args, **kwargs):
        self.logger.setLevel("DEBUG")
        self.logger.debug(*args, **kwargs, exc_info=self.excInfo)


logger = Logger()


def plain_log(msg):
    logger.info(msg)


def info(msg, attach_name=""):
    if LOG_METHOD == "pytest":
        logger.info(msg)
    elif LOG_METHOD == "allure":
        logger.info(msg)
        allure.attach("%s" % msg, attach_name, attachment_type=allure.attachment_type.TEXT)


def error(msg, attach_name=""):
    if LOG_METHOD == "pytest":
        logger.error(msg)
    elif LOG_METHOD == "allure":
        logger.error(msg)
        allure.attach("%s" % msg, attach_name, attachment_type=allure.attachment_type.TEXT)

def warn(msg):
    logger.warn("%s" % msg)

def debug(msg, attach_name=""):
    if LOG_METHOD == "pytest":
        logger.debug(msg)
    elif LOG_METHOD == "allure":
        logger.debug(msg)


if __name__ == '__main__':
    info("--------------------------------", attach_name="999")
    warn("-----------------++-------------")
    debug("--------------------------------")
    error("--------------------------------")
